﻿using System;
using System.Collections;
using System.Collections.Generic;
using System.Linq;
using System.Security.Cryptography;
using System.Text;
using System.Xml;

namespace wojilu
{
    public class PHP
    {
        #region 转换时间为unix时间戳
        /// <summary>
        /// 转换时间为unix时间戳
        /// </summary>
        /// <param name="date">需要传递UTC时间,避免时区误差,例:DataTime.UTCNow</param>
        /// <returns></returns>
        public static double ConvertToUnixTimestamp(DateTime date)
        {
            DateTime origin = new DateTime(1970, 1, 1, 0, 0, 0, 0);
            TimeSpan diff = date - origin;
            return Math.Floor(diff.TotalSeconds);
        }

        public static int UnixTimestamp()
        {
            DateTime time = TimeZone.CurrentTimeZone.ToLocalTime(new DateTime(0x7b2, 1, 1));
            string str = DateTime.Parse(DateTime.Now.ToString()).Subtract(time).Ticks.ToString();
            return Convert.ToInt32(str.Substring(0, str.Length - 7));
        }

        #endregion

        public static long PHP_Time()
        {
            DateTime time = new DateTime(0x7b2, 1, 1);
            return ((DateTime.UtcNow.Ticks - time.Ticks) / 0x989680L);
        }

        public static string PHP_UrlEncode(string str)
        {
            string str2 = string.Empty;
            string str3 = "_-.1234567890abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ";
            for (int i = 0; i < str.Length; i++)
            {
                string str4 = str.Substring(i, 1);
                if (str3.Contains(str4))
                {
                    str2 = str2 + str4;
                }
                else
                {
                    foreach (byte num2 in Encoding.Default.GetBytes(str4))
                    {
                        str2 = str2 + "%" + num2.ToString("X");
                    }
                }
            }
            return str2;
        }

        private static void GetItems(XmlNode node, Hashtable ht, ref int index, string itemNodeName, string attrIdName)
        {
            if (node.SelectNodes(itemNodeName).Count != 0)
            {
                foreach (XmlNode node2 in node.ChildNodes)
                {
                    if (node2.ChildNodes.Count > 1)
                    {
                        GetItems(node2, ht, ref index, itemNodeName, attrIdName);
                    }
                    else
                    {
                        ht.Add(node2.Attributes[attrIdName].Value, node2.InnerText);
                        index++;
                    }
                }
            }
        }

        public static string Serialize(Hashtable args, bool htmlOn)
        {
            return Serialize(args, htmlOn, 1);
        }

        private static string Serialize(Hashtable args, bool htmlOn, int level)
        {
            StringBuilder builder = new StringBuilder();
            if (level <= 1)
            {
                builder.AppendLine("<?xml version=\"1.0\" encoding=\"ISO-8859-1\"?>");
                builder.AppendLine("<root>");
            }
            foreach (DictionaryEntry entry in args)
            {
                if (entry.Value is Hashtable)
                {
                    builder.AppendLine("<item id=\"" + entry.Key.ToString() + "\">");
                    builder.AppendLine(Serialize((Hashtable)entry.Value, htmlOn, level + 1));
                    builder.AppendLine("</item>");
                }
                else
                {
                    builder.AppendFormat(htmlOn ? "<item id=\"{0}\"><![CDATA[{1}]]></item>\r\n" : "<item id=\"{0}\">{1}</item>\r\n", entry.Key, entry.Value);
                }
            }
            if (level == 1)
            {
                builder.AppendLine("</root>");
            }
            return builder.ToString();
        }

        public static Hashtable UnSerialize(string xml)
        {
            return UnSerialize(xml, "root", "item", "id");
        }

        public static Hashtable UnSerialize(string xml, string rootNodeName, string itemNodeName, string attrIdName)
        {
            Hashtable ht = new Hashtable();
            try
            {
                XmlDocument document = new XmlDocument();
                document.LoadXml(xml);
                XmlNode node = document.SelectSingleNode(rootNodeName);
                int index = 0;
                GetItems(node, ht, ref index, itemNodeName, attrIdName);
            }
            catch
            {
            }
            Console.WriteLine("----------------HT---------------------");
            return ht;
        }

        private static string AuthCode(string source, string operation, string key, int expiry)
        {
            if (source.StrIsNullOrEmpty() || key.StrIsNullOrEmpty())
            {
                return "";
            }
            int length = 4;
            key = MD5(key);
            string str = MD5(strUtil.CutStr(key, 0, 0x10));
            string str2 = MD5(strUtil.CutStr(key, 0x10, 0x10));
            string str3 = (length > 0) ? ((operation == "DECODE") ? strUtil.CutStr(source, 0, length) : Rand.RandomString(length)) : "";
            string pass = str + MD5(str + str3);
            if (operation == "DECODE")
            {
                byte[] buffer;
                try
                {
                    buffer = Convert.FromBase64String(strUtil.CutStr(source, length));
                }
                catch
                {
                    try
                    {
                        buffer = Convert.FromBase64String(strUtil.CutStr(source + "=", length));
                    }
                    catch
                    {
                        try
                        {
                            buffer = Convert.FromBase64String(strUtil.CutStr(source + "==", length));
                        }
                        catch
                        {
                            return "";
                        }
                    }
                }
                string str5 = Encoding.Default.GetString(RC4(buffer, pass));
                if (strUtil.CutStr(str5, 10, 0x10) == strUtil.CutStr(MD5(strUtil.CutStr(str5, 0x1a) + str2), 0, 0x10))
                {
                    return strUtil.CutStr(str5, 0x1a);
                }
                return "";
            }
            source = "0000000000" + strUtil.CutStr(MD5(source + str2), 0, 0x10) + source;
            byte[] inArray = RC4(Encoding.Default.GetBytes(source), pass);
            return (str3 + Convert.ToBase64String(inArray));
        }

        public static string AuthCodeDecode(string str, string key)
        {
            return AuthCode(str, "DECODE", key, 0);
        }

        public static string AuthCodeDecode(string str, string key, int expiry)
        {
            return AuthCode(str, "DECODE", key, expiry);
        }

        public static string AuthCodeEncode(string str, string key)
        {
            return AuthCode(str, "ENCODE", key, 0);
        }

        public static string AuthCodeEncode(string str, string key, int expiry)
        {
            return AuthCode(str, "ENCODE", key, expiry);
        }

        private static byte[] GetKey(byte[] pass, int kLen)
        {
            byte[] buffer = new byte[kLen];
            for (long i = 0; i < kLen; i++)
            {
                buffer[(int)((IntPtr)i)] = (byte)i;
            }
            long num2 = 0;
            for (long j = 0; j < kLen; j++)
            {
                num2 = ((num2 + buffer[(int)((IntPtr)j)]) + pass[(int)((IntPtr)(j % ((long)pass.Length)))]) % ((long)kLen);
                byte num4 = buffer[(int)((IntPtr)j)];
                buffer[(int)((IntPtr)j)] = buffer[(int)((IntPtr)num2)];
                buffer[(int)((IntPtr)num2)] = num4;
            }
            return buffer;
        }

        private static byte[] RC4(byte[] input, string pass)
        {
            if ((input == null) || (pass == null))
            {
                return null;
            }
            Encoding encoding = Encoding.Default;
            byte[] buffer = new byte[input.Length];
            byte[] key = GetKey(encoding.GetBytes(pass), 0x100);
            long num = 0;
            long num2 = 0;
            for (long i = 0; i < input.Length; i++)
            {
                num = (num + 1) % ((long)key.Length);
                num2 = (num2 + key[(int)((IntPtr)num)]) % ((long)key.Length);
                byte num4 = key[(int)((IntPtr)num)];
                key[(int)((IntPtr)num)] = key[(int)((IntPtr)num2)];
                key[(int)((IntPtr)num2)] = num4;
                byte num5 = input[(int)((IntPtr)i)];
                byte num6 = key[(key[(int)((IntPtr)num)] + key[(int)((IntPtr)num2)]) % key.Length];
                buffer[(int)((IntPtr)i)] = (byte)(num5 ^ num6);
            }
            return buffer;
        }

        #region MD5函数
        /// <summary>
        /// MD5函数
        /// </summary>
        /// <param name="str">原始字符串</param>
        /// <returns>MD5结果</returns>
        public static string MD5(string str)
        {
            byte[] b = Encoding.UTF8.GetBytes(str);
            b = new MD5CryptoServiceProvider().ComputeHash(b);
            string ret = "";
            for (int i = 0; i < b.Length; i++)
                ret += b[i].ToString("x").PadLeft(2, '0');

            return ret;
        }
        #endregion

    }
}
